package eu.sudparis.it.opp.demo.model;

import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.*;

import edu.uci.ics.jung.algorithms.cluster.EdgeBetweennessClusterer;
import eu.sudparis.it.opp.Community;
import eu.sudparis.it.opp.TimeSeries;
import eu.sudparis.it.opp.Interceptor;
import eu.sudparis.it.opp.Node;
import eu.sudparis.it.opp.demo.GraphAnalysis;
import eu.sudparis.it.opp.graph.Edge;
import eu.sudparis.it.opp.graph.Modularity;
import eu.sudparis.it.opp.graph.Snapshot;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.UndirectedSparseGraph;

public class CommunityAnalyzer implements Interceptor {
	private EdgeBetweennessClusterer<Integer, Edge> detector = null;
	private Set<Set<Integer>> groups = null;
	public List<Community<Actor>> current = new ArrayList<Community<Actor>>();
	public static PrintStream ps = null;
	static {
		try {
			ps = new PrintStream("G://reality_set/community_size.txt");
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void init(TimeSeries g) {
		// TODO Auto-generated method stub

	}

	@Override
	public void before(TimeSeries g) {
		// TODO Auto-generated method stub
		if (g.currentTime % (60 * 30) == 0) {
			Collection<Actor> allnode = new ArrayList<Actor>();
			HashMap<Integer, Actor> mapping = new HashMap<Integer, Actor>();
			for (Node nd : g.graph.graph.values()) {
				allnode.add((Actor) nd.chain_of_responsibility);
				mapping.put(nd.id, (Actor) nd.chain_of_responsibility);
			}
			int i = 1;
			double score = iteraction(i++, new Snapshot<Actor>(allnode));
			if (score == -10)
				return;
			double score_temp = 0;
			Set<Set<Integer>> temp = this.groups;
			while ((score_temp = this.iteraction(i++, new Snapshot<Actor>(
					allnode))) > score) {
				temp = this.groups;
				score = score_temp;
			}
			current.clear();
			if (temp != null) {
				for (Set<Integer> cos : temp) {
					if (cos.size() >= 3) {
						List<Actor> actresses = new ArrayList<Actor>();
						for (int co : cos) {
							actresses.add(mapping.get(co));
						}
						Community<Actor> actors = new Community<Actor>(
								actresses, g);
						current.add(actors);
					}
				}
				ps.println(this.current.size() + "\t"
						+ GraphAnalysis.toDate(g.currentTime));
			}
		}

	}

	private double iteraction(int i, Snapshot<Actor> actors) {
		if (actors.edges.size() < 10)
			return -10;
		Graph<Integer, Edge> graph = new UndirectedSparseGraph<Integer, Edge>();
		for (Actor act : actors.nodes) {
			graph.addVertex(act.id);
		}
		for (Edge edge : actors.edges) {
			graph.addEdge(edge, edge.nda, edge.ndb);
		}
		detector = new EdgeBetweennessClusterer<Integer, Edge>(i);
		this.groups = detector.transform(graph);
		List<Edge> edges = detector.getEdgesRemoved();
		actors.edges.removeAll(edges);
		return new Modularity<Actor>(actors,this.groups).calculate();
	}

	public boolean inSameGroup(int a, int b) {// the modularity of current
												// groups
		for (Set<Integer> group : groups) {
			if (group.contains(a) && group.contains(b))
				return true;
		}
		return false;
	}

	@Override
	public void after(TimeSeries g) {
		// TODO Auto-generated method stub

	}

	@Override
	public void fini(TimeSeries g) {
		// TODO Auto-generated method stub

	}

}
